// SPDX-License-Identifier: GPL-2.0
#include "ocfs2_block_dev.h"
#include "cluster/masklog.h"

static int bdev_test(struct inode *inode, void *data)
{
	return BDEV_I(inode)->bdev.bd_dev == *(dev_t *)data;
}

static int bdev_set(struct inode *inode, void *data)
{
	return -EPERM;
}

/*
 * Return an already referenced block device or NULL.
 */
struct block_device *ocfs2_bdget(dev_t dev)
{
	struct block_device *bdev = NULL;
	struct inode *inode = NULL;

	/*
	 * If inode is not in inode cache, bdev_set() will return
	 * an error, causing iget5_locked() to return NULL. So we
	 * don't need to deal with inodes with the I_NEW flag.
	 */
	inode = iget5_locked(blockdev_superblock, hash(dev),
			bdev_test, bdev_set, &dev);
	if (!inode) {
		mlog(ML_ERROR,
		    "Inode of block device[%u:%u] is not in inode cache.\n",
		    MAJOR(dev), MINOR(dev));
		return NULL;
	}
	bdev = &BDEV_I(inode)->bdev;
	return bdev;
}
EXPORT_SYMBOL_GPL(ocfs2_bdget);

void ocfs2_bdput(struct block_device *bdev)
{
	iput(bdev->bd_inode);
}
EXPORT_SYMBOL_GPL(ocfs2_bdput);
